/*
 * 工具..比如自動fo-fo,自動記錄,自動...本來也都是自動的麽v0.1
 * @author @bonex2 
 */
package main;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.sql.Timestamp;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Random;
import java.util.Set;
import java.util.Vector;

import twitter4j.IDs;
import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterFactory;
import twitter4j.User;

public class Utils extends Thread {

	/**
	 * 增加获得Twitter的共通方法
	 * 
	 * @return
	 */
	static public Twitter getTwitter() {
		return new TwitterFactory("").getInstance(Common.USER, Common.PASSWORD);
	}

	public void run() {
		while (true) {
			try {
				// 2010-2-18 23:38 修改autoFollow的請求.防止因爲上限導致不能執行正常循環
				try {
					long t0 = System.currentTimeMillis();
					// 自動跟隨,追加機能增加好友到本地DB
					autoFollow();
					long t1 = System.currentTimeMillis();

					System.out.println(Common.DEFAULT_TIME_YMDHMS
							.format(new Date(t1))
							+ " 執行好友檢測共消耗時間 :" + (t1 - t0) + "ms.");
				} catch (Exception e) {
					e.printStackTrace();
				}
				// 2010-2-18 23:38 end
				Thread.sleep(3600000);
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
	}

	/**
	 * 自動跟隨Follower
	 * 
	 * @throws Exception
	 */
	static public void autoFollow() throws Exception {
		// 2010-2-24 1:47 全部使用自己的账号操作
		Twitter twitter = getTwitter();
		// 得到follower的id

		IDs idsFollower = twitter.getFollowersIDs();
		// 得到following的id
		IDs idsFollowing = twitter.getFriendsIDs();
		int[] is1 = idsFollower.getIDs();
		int[] is2 = idsFollowing.getIDs();
		Vector<Integer> vc = new Vector<Integer>();
		// 得到現有的follower的vector
		for (int i = 0; i < is1.length; i++) {
			vc.add(new Integer(is1[i]));
		}
		// 從現有的follower中去除已經following的
		for (int i = 0; i < is2.length; i++) {
			if (vc.contains(new Integer(is2[i]))) {
				vc.remove(new Integer(is2[i]));
			}
		}
		Iterator<Integer> i = vc.iterator();
		// 批量添加未FO的.可能受API操作限制
		int count = 0;
		while (vc.size() > 0 && i.hasNext()) {
			Integer id = i.next();
			twitter.createFriendship(id.intValue(), true);
			count++;
		}
		if (count > 0) {
			twitter.updateStatus("剛才的一個小時裏我又被" + count
					+ "個人/bot尾行了。不知道我家主人會不會擔心我啊…");
		}

		// 更新Friends列表,只增不刪,並且只更新新增的....待商榷
		saveFriendsToDb(vc.toArray(), twitter);

		System.out.println(count + " followers adds to following");
	}

	static public void saveFriendsToDb(Object[] ids) {
		saveFriendsToDb(ids, null);
	}

	/**
	 * 追加/更新ids至本地用戶庫
	 * 
	 * @param ids
	 */
	static public void saveFriendsToDb(Object[] ids, Twitter twitter) {
		long t0 = System.currentTimeMillis();
		try {
			if (twitter == null) {
				twitter = getTwitter();
			}
			// 存放傳入的用戶 (id, sceenName)
			HashMap vUser = new HashMap();
			for (int i = 0; i < ids.length; i++) {
				// 根據ID得到用戶相關信息。耗時太多
				User u = twitter.showUser((Integer) ids[i]);
				vUser.put(Integer.valueOf(u.getId()), u.getScreenName());
			}
			if (vUser.size() > 0) {
				Connection conn = new Dao().getConn();
				// 查詢已存在用戶信息
				String querySql = "SELECT ID, SCREEN_NAME FROM FRIENDS";
				// 插入新的用戶
				String insertSql = "INSERT INTO FRIENDS SET SCREEN_NAME = ? , ID = ? ";
				// 更新已存在用戶
				String updateSql = "UPDATE FRIENDS SET SCREEN_NAME = ? WHERE ID = ?";
				// 是否需要刪除已unfo用戶待定

				Statement stmt = conn.createStatement();
				ResultSet rs = stmt.executeQuery(querySql);
				HashMap vQuery = new HashMap();
				while (rs.next()) {
					UserLite ul = new UserLite(rs);
					vQuery.put(Integer.valueOf(ul.getId()), ul.getScreenName());
				}
				// 循環遍歷傳入的用戶信息
				Set keys = vUser.keySet();
				Iterator i = keys.iterator();
				PreparedStatement prst = null;
				while (i.hasNext()) {
					Integer id = (Integer) (i.next());
					if (vQuery.containsKey(id)) {
						prst = conn.prepareStatement(updateSql);
					} else {
						prst = conn.prepareStatement(insertSql);
					}
					prst.setString(1, vUser.get(id).toString());
					prst.setLong(2, id.longValue());
					prst.execute();
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		long t1 = System.currentTimeMillis();
		System.out.println(Common.DEFAULT_TIME_YMDHMS.format(new Date(t1))
				+ " 執行好友查詢增加消耗時間 :" + (t1 - t0) + "ms.");
	}

	/**
	 * 随机得到友人
	 * 
	 * @return
	 */
	static public UserLite getRandomUser() {
		UserLite user = null;
		try {
			Connection conn = new Dao().getConn();
			String sql = "SELECT ID, SCREEN_NAME FROM FRIENDS";
			ResultSet rs = conn.createStatement().executeQuery(sql);
			Vector vs = new Vector();
			while (rs.next()) {
				UserLite u = new UserLite(rs);
				vs.add(u);
			}
			if (vs.size() > 0) {
				// 優化random代碼,不再开根号
				Random r = new Random();
				double percent = r.nextDouble();
				int v = (int) (percent * (double) vs.size());
				if (v < vs.size()) {
					user = (UserLite) vs.elementAt(v);
				} else {
					user = (UserLite) vs.elementAt(0);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return user;
	}

	static public boolean isSentenceUserable(SentencePair sentence) {
		return (sentence == null) ? false : (sentence.getSentence()
				.contains(Common.USER_MARK));
	}

	/**
	 * 替换一个的友人
	 * 
	 * @param sentence
	 * @param user
	 */
	static public String setSingleUserToSentence(SentencePair sentence,
			UserLite user) {

		String finalSentence = null;
		if (sentence != null && user != null) {
			finalSentence = sentence.getSentence().replace(Common.USER_MARK,
					(Common.USER_TAG + user.getScreenName()));
		}
		return finalSentence;
	}

	/**
	 * 发送一个tweet并且记录下来
	 * 
	 * @param sentence
	 */
	static public void tweetATweet(SentencePair sentence) {
		try {
			Connection conn = new Dao().getConn();
			Twitter twitter = getTwitter();
			UserLite user = null;
			Status status = null;
			String finalSentence = null;

			if (isSentenceUserable(sentence)) {
				// 如果可以替换朋友名,则替换
				user = getRandomUser();
				finalSentence = setSingleUserToSentence(sentence, user);
			} else {
				finalSentence = sentence.getSentence();
			}
			status = twitter.updateStatus(finalSentence);
			// 2010-2-23 23:29追加
			// sentence的id=-1时为系统消息，不记录提到的人物
			if (status != null && status.getId() > 0 && sentence.getId() > 0) {
				// 執行統計更新，並在updateTweetedTime方法中記錄log
				updateTweetedTime(conn, sentence, user, finalSentence, status
						.getCreatedAt());
			} else {
				// 直接記錄log
				Action2Log.insertLog(sentence, user, finalSentence);
			}
			// 2010-2-23 23:29 end
		} catch (Exception e) {
			e.printStackTrace();
			Action2Log.insertLog(new SentencePair(e.getMessage()), null, e
					.getMessage());
		}
	}

	/**
	 * 更新tweeted時間并产生log,将进一步与Action2Log进行整合.这个方法最后会被Action2Log.insertLog的更新版本取代
	 * 
	 * @param conn
	 * @param sentence
	 * @param user
	 * @param finalSentence
	 * @param createAt
	 */
	static public void updateTweetedTime(Connection conn,
			SentencePair sentence, UserLite user, String finalSentence,
			Date createAt) {
		if (sentence.getId() == -1) {
			return;
		}
		try {
			String sql = "UPDATE SENTENCES SET LAST_TWEETED = ?, TWEETED_COUNTS = TWEETED_COUNTS + 1 WHERE ID = ?";
			PreparedStatement stmt = conn.prepareStatement(sql);
			PreparedStatement stmt2 = null;
			stmt.setTimestamp(1, new Timestamp(createAt.getTime()));
			stmt.setLong(2, sentence.getId());
			boolean rs = stmt.execute();
			if (user != null) {
				String sql2 = "UPDATE FRIENDS SET ACTIVE_MENTIONED  = ACTIVE_MENTIONED + 1 WHERE ID = ?";
				stmt2 = conn.prepareStatement(sql2);
				stmt2.setLong(1, user.getId());
				stmt2.execute();
			}
			if (!rs && stmt.getUpdateCount() > 0) {
				Action2Log.insertLog(sentence, user, finalSentence);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

	// 2010-2-23 23:29追加
	/**
	 * 0:00首先得到过去一天说话的数量
	 * 
	 * @param conn
	 * @return
	 */
	static public int getSaid(Connection conn) {
		int count = -1;
		String sql = "SELECT COUNT(ID) FROM SENTENCES WHERE (TO_DAYS(NOW()) - TO_DAYS(LAST_TWEETED)) = 1";
		Statement stmt;
		try {
			stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery(sql);
			if (rs.next()) {
				count = rs.getInt(1);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return count;
	}

	/**
	 * 0:00首先得到过去一天调戏的人的数量
	 */
	static public int getMentionedUserCount(Connection conn) {
		int count = -1;
		String sql = "SELECT COUNT(ID) FROM FRIENDS WHERE (TO_DAYS(NOW()) - TO_DAYS(LAST_MENTIONED)) = 1";
		Statement stmt;
		try {
			stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery(sql);
			if (rs.next()) {
				count = rs.getInt(1);
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return count;
	}

	/**
	 * 返回最近一次被调戏的人
	 * 
	 * @param conn
	 * @return
	 */
	static public UserLite getMentionedUser(Connection conn) {
		UserLite user = null;
		String sql = "SELECT ID, SCREEN_NAME FROM FRIENDS WHERE LAST_MENTIONED IN (SELECT MAX(LAST_MENTIONED) FROM FRIENDS) ";
		Statement stmt;
		try {
			stmt = conn.createStatement();
			ResultSet rs = stmt.executeQuery(sql);
			if (rs.next()) {
				user = new UserLite();
				user.setId(rs.getInt("ID"));
				user.setScreenName(rs.getString("SCREEN_NAME"));
			}
		} catch (SQLException e) {
			e.printStackTrace();
		}
		return user;
	}
	// 2010-2-23 23:29 end
}
